/**
 *  The JooScript Basics Head
 *
 *  Copyright (c) 2010 Evgen Burzak <buzzilo at gmail.moc>
 *  Released under the MIT/X License
 */

// statically define magic keywords while compiler is not ready yet
__FILE__ = __PATH__ = __FUNC__ = __CLASS__ = __GROUP__ = __LINE__ = "";

// Begin JooScript body
(function(){

  // exit if jooscript is loaded to avoid problemes,
  // it may be in case when jooscript loaded from Worker stub
  if(typeof $jooscript != "undefined") return;

/*
 * Env variables for various platform
 *
 * Copyright (c) 2010 Evgen Burzak <buzzilo at gmail.moc>
 * Released under the MIT/X License
 */

(function(){

  var typeof_win = typeof window;

  var hasWindow = !(typeof_win == "undefined" || 
                    (typeof_win == "object" && window == null));

  $globals = hasWindow ? window : this;

  var hasDocument = !!$globals['document'];
  var hasNavigator = !!$globals['navigator'];

  $root = hasDocument ? document : {};

  $isCLI = !hasNavigator;

  $isWorker = !$isCLI && !hasWindow;

})();
/*
 * Console stub and trace method
 *
 * Copyright (c) 2010 Evgen Burzak <buzzilo at gmail.moc>
 * Released under the MIT/X License
 */

(function() {

  // enable trace by default for browser, and disable for Workers
  var trace_disable = typeof $trace_disable !='undefined' ? $trace_disable : $isWorker;
  
  if (typeof console == "undefined") {
    $globals["console"] = {
      log: function() {
        var o = []
        for (var i=0; i<arguments.length; i++)
          o.push(arguments[i])
        typeof alert == "undefined" ? print.apply(null,o) : alert(o.join(", "));
      }, 
      dir: function() {
        // todo
      }
    }
  }

  var trace = !trace_disable ? 
    function () {
      if (console)
        console.log(["trace: ", Array.prototype.slice.call(arguments, 0).join(" ")].join(""))
    } :
    function (){};

  $globals["trace"] = trace;
})();
/*
 * DOMException stub for Internet Explorer
 *
 */

var _DOMException = (function() {

  var _DOMException = function(s) {
    this.code = this[s];
    this.message = s +': DOM Exception ' + this.code;
  };

  var p = _DOMException.prototype = new Error;
  p.INDEX_SIZE_ERR = 1;
  p.DOMSTRING_SIZE_ERR = 2;
  p.HIERARCHY_REQUEST_ERR = 3;
  p.WRONG_DOCUMENT_ERR = 4;
  p.INVALID_CHARACTER_ERR = 5;
  p.NO_DATA_ALLOWED_ERR = 6;
  p.NO_MODIFICATION_ALLOWED_ERR = 7;
  p.NOT_FOUND_ERR = 8;
  p.NOT_SUPPORTED_ERR = 9;
  p.INUSE_ATTRIBUTE_ERR = 10;
  p.INVALID_STATE_ERR = 11;
  p.SYNTAX_ERR = 12;
  p.INVALID_MODIFICATION_ERR = 13;
  p.NAMESPACE_ERR = 14;
  p.INVALID_ACCESS_ERR = 15;
  p.VALIDATION_ERR = 16;
  p.TYPE_MISMATCH_ERR = 17;

  if (!$globals["DOMException"]) $globals["DOMException"] = _DOMException;

  return _DOMException;

})();
/*
 * (c)2006 Jesse Skinner/Dean Edwards/Matthias Miller/John Resig
 * Special thanks to Dan Webb's domready.js Prototype extension
 * and Simon Willison's addLoadEvent
 *
 * For more info, see:
 * http://www.thefutureoftheweb.com/blog/adddomloadevent
 * http://dean.edwards.name/weblog/2006/06/again/
 * http://www.vivabit.com/bollocks/2006/06/21/a-dom-ready-extension-for-prototype
 * http://simon.incutio.com/archive/2004/05/26/addLoadEvent
 * 
 *
 * To use: call addDOMLoadEvent one or more times with functions, ie:
 *
 *    function something() {
 *       // do something
 *    }
 *    addDOMLoadEvent(something);
 *
 *    addDOMLoadEvent(function() {
 *        // do other stuff
 *    });
 *
 */
 
addDOMLoadEvent = (function(){
    // create event function stack
    var load_events = [],
        load_timer,
        script,
        exec,
        old_onload;

    function init () {
        init.done = true;

        // kill the timer
        clearInterval(load_timer);

        // execute each function in the stack in the order they were added
        while (exec = load_events.shift())
            exec();

        if (script) script.onreadystatechange = '';

        //window.__init__ = null
    };

    // make it global to using inside eval()
    $globals.__init__ = init;

    return function (func) {
        // if the init function was already ran, just run this function now and stop
        if (init.done) return func();

        if (!load_events[0]) {
            // for Mozilla/Opera9
            if (!$root.__w3c_fake && $root.addEventListener)
                $root.addEventListener("DOMContentLoaded", init, false);

            // for Internet Explorer
            eval("/*@cc_on @*/");
            eval('/*@if(@_win32)'+
                    'document.write("<script id=__ie_onload defer src=//0><\/scr"+"ipt>");'+
                    'script=document.getElementById("__ie_onload");'+
                    'script.onreadystatechange=function(){'+
                        'if(this.readyState=="complete")'+
                            '__init__();'+
                    '};'+
                    'document.onreadystatechange=function(){'+
                        'if(document.readyState=="complete"){'+
                            '__init__();document.onreadystatechange=null;'+
                        '}'+
                    '}'+
                '@*/'+
            '/*@end@*/')

            if( !$isCLI && !$isWorker ) {
                // for Safari
                if (/WebKit/i.test(navigator.userAgent)) { // sniff
                    load_timer = setInterval(function() {
                        if (/loaded|complete/.test(document.readyState))
                            init(); // call the onload handler
                    }, 10);
                }
            }
            // is it CLI ?
            // just fire init at the end of script, because of some envs does not provide
            // setTimeout/Interval method

            // for other browsers set the window.onload, but also execute the old window.onload
            old_onload = $globals.onload;
            $globals.onload = function() {
                init();
                if (old_onload) old_onload();
            };
        }

        load_events.push(func);
    }
})();

/*
 * JavaScript hacks
 *
 * Copyright (c) 2010 Evgen Burzak <buzzilo at gmail.moc>
 * Released under the MIT/X License
 */
(function(){

  // On iPhones, Safari does not set "caller" property if function called
  // with apply() or call(), but there is workaround for this problem ...
  function $a(){
    function $b () {
      return $b.caller === $a;
    }
    return !$b.apply(null, []);
  }

  var applyPatching = $a();

  var funProto = Function.prototype;

  if(applyPatching) {
    funProto.__native__apply = funProto.apply
    funProto.__native__call = funProto.call
    funProto.apply = function __apply__(context, args) {
      this.__caller__ = __apply__.caller
      return this.__native__apply(context, args)
    }
    funProto.call = function __call__() {
      this.__caller__ = __call__.caller
      return this.__native__call.__native__apply(this, arguments)
    }
  }

  // Emulate new constructor purely with javascript
  function _new(){
    var obj = {};
    // IE suck at this point, so that it is impossible to define parent of 
    // an object instance. Is there any workaround?
    obj.__proto__ = this.prototype
    // fixme is it always works?
    var x = this.apply(obj, arguments);
    return x !== null && typeof x === "object" ? x : obj;
  }

  // deprecated function constructor is a static 'new' method in JooScript
  funProto['new'] = _new

})();

/**
 *  Event class
 *
 *  Copyright (c) 2010 Evgen Burzak <buzzilo at gmail.moc>
 *  Released under the MIT/X License
 *
 *  Using example:
 *  
 *  var ev = $Event()
 *  ev.useCapture = false
 *  ev.when("mousedown", element, function(msg){
 *    trace("you touch me!", msg.target.id)
 *  });
 *  ev.once("mouseclick", element, function(msg){
 *    trace("you click me!", msg.target.id)
 *  });
 *  ev.dispatch("mousedown", element)
 *  ev.dispatch("mouseclick", element)
 *  ev.remove("mousedown", element)
 *
 *  Ideas:
 *
 *  ev.record() - save events
 *  ev.play() - play saved events
 *  ev.clear() - clear recorded events
 *  ev.cassette[] - records container
 *
 *  TODO:
 *  
 */
var _Event = 
(function()
{
  // if event added without target it will register in global scope
  var globalListeners = [];

  // Event constructor
  function _Event() {

    if( _Event.caller === _Event ) return this;
    var self = new _Event;

    self.useCapture = false;

    self.__class__ = _Event

    var _new = _Event.prototype.__new__,
        _when = _Event.prototype.when,
        _dispatch = _Event.prototype.dispatch,
        _remove = _Event.prototype.remove;

    _new(self);

    self.when = function(eventType, target, handler){
      return _when(self, eventType, target, handler, false)
    }

    self.once = function(eventType, target, handler){
      return _when(self, eventType, target, handler, true)
    }

    self.dispatch = function(eventType, target){
      return _dispatch(self, eventType, target)
    }

    self.remove = function(eventType, target){
      return _remove(self, eventType, target)
    }

    return self
  }

  _Event.className = "Event";

  var DOMContentLoaded = "DOMContentLoaded",
      contentloaded = "contentloaded";

  function parseEventType(eventType) {
    var evtype = (typeof eventType == "string" ? eventType : eventType.type).toLowerCase();
    if(evtype == DOMContentLoaded)
      return contentloaded
    return evtype
  }

  // todo optimize for speed, because of problem is 
  // that if it using for interactive events such as mousemove ,
  // loops may take good piece of time ...
  // As variant, event handlers may be called in generated function.
  function fireEvent(type, listeners) {
    var listener, breakChain
    for(var i=0; i<listeners.length; i++) {
      listener = listeners[i]
      if(!listener) continue;
      if(listener.type == type) {
        // handler may raise exception, so it will fired not once, 
        // so throw the exception soon
        var exception
        try{
          breakChain = listener.handler.call(listener.context, {})
        }catch(e){
          exception = e
        }
        if( listener.fireOnce ) listeners[i] = null
        if( exception ) throw exception
        if( breakChain ) break;
      }
    }
  }

  function clearEvent(type, handler, listeners) {
    var listener
    for(var i=0; i<listeners.length; i++) {
      listener = listeners[i]
      if(!listener) continue;
      if(listener.type == type && listener.handler === handler)
        listeners[i] = null
    }
  }

  _Event.prototype = 
  {
    "__class__" : _Event,
    // constructor
    "__new__" : function(self) {
        self.__listeners__ = []
    },
    // where eventType is object (eg, {type: "type"}) or string "type"
    "when" : function(self, eventType, target, handler, fireOnce){
      //trace("when", eventType, target, handler)
      var listeners, context
      if(handler == undefined || handler == null) {
        handler = target
        listeners = globalListeners
      }
      else
        listeners = self.__listeners__

      var evtype = parseEventType(eventType)

      if(evtype == contentloaded)
        addDOMLoadEvent(function(){
          fireEvent(contentloaded, listeners)
        });
      else {
      }
      listeners.push({
        type : evtype,
        handler : handler,
        context : self,
        fireOnce : fireOnce
      })
    },

    "dispatch" :function(self, eventType, target){ 
      //trace("dispatch", eventType, target)
      var evtype = parseEventType(eventType)
      fireEvent(evtype, target == undefined ? globalListeners : self.__listeners__)
    },

    "remove" : function(self, eventType, target, handler){ 
      //trace("remove", eventType, target)
      var listeners, context
      if(handler == undefined) {
        handler = target
        listeners = globalListeners
      }
      else
        listeners = self.__listeners__
      var evtype = parseEventType(eventType)
      clearEvent(evtype, handler, listeners)
    }

  };

  _Event['new'] = function(){
    return new this;
  }

  var _event = _Event();

  // Bind it to the Event class as static methods
  _Event.when = _event.when
  _Event.once = _event.once
  _Event.dispatch = _event.dispatch
  _Event.remove = _event.remove

  return _Event;

})();
/*
 * Browser Wars, Episode One: Unified $root Object Model
 *
 * A long time ago in a galaxy far, far away ...
 *
 * W3C standards is not ideal, but at least it is supporting by four of five 
 * main browser vendors on the market, except ... 
 * This script roughly injects W3C-compliant wrappers for native IE's methods and 
 * added some useful things to browsers on another side from IE model.
 *
 * Kudos to quirksmode.org authors for excellent book, which save me years of 
 * digging all of these *things*.
 *
 * Usage
 * 
 * Call `w3c(node)` to inject wrappers.
 *
 * //////////////////////////////////////////////////////////////////////////////
 *
 * @refers http://quirksmode.org
 * @refers http://www.howtocreate.co.uk/tutorials/javascript/domevents
 * @refers http://javascript.ru/blog/Andrej-Paranichev/Vvedenie-sobytiya
 * @refers http://developer.mozilla.org/en/
 *
 * @spec http://www.w3.org/TR/1999/WD-DOM-Level-2-19990923/events.html
 *
 * Copyright (c) 2010 Evgen Burzak <buzzilo at gmail.moc>
 * Released under the MIT/X License
 */
(function(){

  if($isCLI || $isWorker) return;

  // hello -> Hello
  function capitalize(word) {
    return word.substr(0, 1).toUpperCase() + word.substr(1);
  };

  function updateObject(obj, addMe) {
    for(var x in addMe) {
      if(!(x in Object.prototype)) { // filter out prototype additions from other potential libraries
        if(x != "__w3c_fake" &&  // ... and some internals
            x != "toString" && 
            x != "__proto__" && 
            x != "valueOf") {
          obj[x] = addMe[x];
        }
      }
    }
  };

  var win = $globals, doc = $root;
  
  // check for proprietary IE DOM members
  if(!(doc.uniqueID && doc.expando)) {
    // stub for standard-compliant browser
    // todo mouseleave, mouseenter, mouseButton..
    win.w3c = function(){};
    w3c.all = w3c;
    return;
  }
  // already faked
  if(win.__w3c_fake) return;

  // Dark side
  //

  // @todo eval()

  // wtf!? setTimeout does not handle arguments !...
  /* 
  win.IESetTimeout = win.setTimeout;
  win.setTimeout = function (func, ms) {
    var args = [];
    for(var i=2; i<arguments.length; i++) args.push(arguments[i]);
    return win.IESetTimeout(function () {
      func.apply(win, args);
    }, ms);
  };
  */

  // window.event object is not keeping injected props, so we
  // need to create our own
  function eventObject () {
    return {
      type           : null,
      target         : null,
      relatedTarget  : null,
      currentTarget  : null,
      offsetParent   : null,
      offsetTop  : null,
      offsetLeft : null,
      screenX    : null,
      screenY    : null,
      pageX      : null,
      pageY      : null,
      altKey     : null,
      shiftKey   : null,
      ctrlKey    : null,
      metaKey    : null,
      button     : null,
      // see below
      mouseButton: null, 
      charCode   : null,
      keyCode    : null,
      // native IE event object
      IEvent     : $root.createEventObject(),
      preventDefault : function () {
        event.returnValue = false
      },
      stopPropagation : function () {
        event.cancelBubble = true
      }
    }
  };

  // mimic method of W3C's element.addEventListener() and 
  // element.removeEventListener()
  //
  // note for me: 
  //
  //keypress works for *characters* typed, across browsers, but 
  //the event return has a charCode in firefox and a keyCode in IE.

  //to capture any key (function/controlkeys) keydown and keyup are more 
  //reliable, though you lose the case when catching alpha characters.

  //Not all elements handle all the key events- $root does, in firefox, 
  //and either $root.documentElement or $root.body in IE, depending on 
  //whether you use a doctype or not.

  //textareas and text inputs handle all the key events across browsers.
  //

  // @fixme `load` event and dynamically added scripts
  //
  var keyableElements = { textarea: true, input: true, select: true, body: true },
      keyEvents = { keydown: "keydown", keyup: "keyup", keypress: "keypress" },
      mouseEvents = { mouseenter: "mouseenter", mouseleave: "mouseleave", mousemove: "mousemove", 
                      mouseup: "mouseup", mousedown: "mousedown", click: "click" };

  function addEventListener(eventType, func, capture /*todo*/) {
    if (arguments.length < 3)
      throw new Error("Not enough arguments");
    if (typeof func != "function") 
      throw new Error("Event handler is not a function");

    // convert event to string
    eventType = "" + eventType;
    // convert capture to boolean
    capture = !!capture;

    var isWindowObject = 'opener' in this,  // because of `this == window` is false
        isMouseEvent = eventType in mouseEvents,
        insideElement = true;

    // exit, if it is keyboard event and the element is not keyable (standard behavior)
    if (eventType in keyEvents)
      if (!((this.tagName && (this.tagName.toLowerCase() in keyableElements)) ||
            this === $root || isWindowObject)) 
        return;

    var eo = eventObject(), 
        // in IE, `window` is not receiving neither mouse nor keyboard events, 
        // so attach it to `$root`
        el = isWindowObject && (eventType in keyEvents || eventType in mouseEvents) ? doc : this,
        context = this,
        // event handler is function wrapped 
        hdlr = "__ievent_hdlr_" + (capture ? "capture" : "nocapture");


    // IE has a bug: `mousedown`, `mousemove` fired even if cursor outside of 
    // the element. It's simple hack to make it like in others.
    //function enterElement () { insideElement = true }
    //function leaveElement () { insideElement = false }
    //el.attachEvent("onmouseenter", enterElement);
    //el.attachEvent("onmouseleave", leaveElement);

    // shim for interactive events
    //
    var interactionEventHandler = function () {
      //if (isMouseEvent && !insideElement) return;
      // there is some evidence that just event is faster than window.event
      eo.type           = event.type;
      eo.target         = event.srcElement;
      eo.relatedTarget  = event.fromElement || event.toElement || null;
      // -- fixme, http://www.quirksmode.org/js/findpos.html
      eo.currentTarget  = context;
      eo.offsetParent   = event.srcElement && event.srcElement.parentNode || null; 
      // --
      eo.offsetTop  = event.offsetX;
      eo.offsetLeft = event.offsetY;
      eo.screenX    = event.screenX;
      eo.screenY    = event.screenY;
      eo.pageX      = event.clientX + $root.body.scrollLeft + $root.documentElement.scrollLeft;
      eo.pageY      = event.clientY + $root.body.scrollTop + $root.documentElement.scrollTop;
      eo.altKey     = event.altKey;
      eo.shiftKey   = event.shiftKey;
      eo.ctrlKey    = event.ctrlKey;
      eo.metaKey    = false; // ??
      eo.keyCode    = event.keyCode;
      eo.charCode   = eventType == "keypress" ? event.keyCode : 0; 
      /*
        Note:
        The Microsoft implementation is the only one that makes sense. button is a bitmask:
          1 - Left button
          2 - Right button
          4 - Middle button

        W3C's definition is:
          0 - Left button
          1 - Middle button
          2 - Right button

        0 should mean "no button pressed", any other meaning is silly. 
        Besides these values cannot be combined into a bitmask: you'll never know 
        whether the left button has been pressed. This definition is very shoddy work. 
      */
      if (event.button == 1)
        eo.button   = 0;
      else if (event.button == 2)
        eo.button   = 2;
      else if (event.button == 4)
        eo.button   = 1;

      // I'd like to add new event property to W3C object: mouseButton, which will reflect 
      // MS idea. (todo W3C hack) 
      eo.mouseButton = event.button;

      // is it working?
      func.call(context, eo);
    }

    // shim for DOM events  
    //
    // todo prev/next values
    var DOMEventHandler = function () {
      var e = event;
      var deo = {
        "type": ""
      }
      deo.type = eventType
      if(eventType === "DOMAttrModified") {
        //An integer indicating in which way the Attr was changed.
        //
        //The Attr was just added.
        deo.ADDITION = 2
        //The Attr was modified in place.
        deo.MODIFICATION = 1
        //The Attr was just removed.
        deo.REMOVAL = 3

        deo.target = e.srcElement
        deo.relatedNode = null
        deo.attrChange = 1 // todo 
        deo.attrName = e.propertyName.split('.')[0]
        deo.prevValue = null // todo
        deo.newValue = deo.target[deo.attrName]
        // fixme in DOM spec event DOMAttrModified should not be fired 
        // if attribute is not part of the DOM node ... there is quick fix for that
        if(deo.attrName == 'innerHTML' || 
            deo.attrName == 'innerText' || 
            typeof deo.newValue == 'function')
              return;
      }
      func.call(context, deo);
    }

    if(eventType.indexOf('DOM') === 0) {
      //if(eventType === "DOMAttrModified")
      func[hdlr] = DOMEventHandler;
    }
    else
      func[hdlr] = interactionEventHandler;

    if (eventType === "DOMContentLoaded")
      addDOMLoadEvent(func[hdlr]);
    else if (eventType === "DOMAttrModified")
      el.attachEvent("onpropertychange", func[hdlr]);
    else
      el.attachEvent("on" + eventType, func[hdlr]);

    //func["__ievent_elenter"] = enterElement
    //func["__ievent_elleave"] = leaveElement
  };

  function removeEventListener(eventType, func, capture /*todo*/) {
    var hdlr = "__ievent_hdlr_" + (capture ? "cap" : "nocap");
    // IE may raise 'type mismatch' exception if event handler is undefined
    if (!func[hdlr]) return;
    this.detachEvent("on" + eventType, func[hdlr]);
    //this.detachEvent("on" + eventType, func["__ievent_elenter"]);
    //this.detachEvent("on" + eventType, func["__ievent_elleave"]);
  }

  function dispatchEvent(evtObj) {
    return this.fireEvent("on" + evtObj.type, evtObj.IEvent);
  };

  function MimicStandardBehavior () {
    var a = arguments, element;

    for (var i=0; i<a.length; i++) {
      if (!a[i]) {
        continue;
      } else if (typeof a[i] == 'string') {
        element = $root.getElementById(a[i])
      } else if (typeof a[i] == 'object') {
        element = a[i]
      }

      // pass, the element has been exploited
      if (element.__w3c_fake) continue;

      // inject code
      //
      element.addEventListener = addEventListener;
      element.removeEventListener = removeEventListener;
      element.dispatchEvent = dispatchEvent;
      element.__w3c_fake = true;
    }
  };

  // Missed in IE (even in 8)
  var _HTMLElement;

  // in this hack is using faked $root.createElement method,
  // it allow using one method for extending elements on both sides
  //
  // @fixme dynamically loaded scripts
  //var __script = [];

  $root.__native__createElement = $root.createElement;
  $root.createElement = function (elName) {
    // for unknown elements tagName will be in mixed case...
    if(/^[a-z]+$/i.test(elName))
      elName = elName.toUpperCase()

    var el = $root.__native__createElement(elName),
        tagName = el.tagName,
        HTMLxElement = window["HTML" + capitalize(tagName.toLowerCase()) + "Element"],
        newElement = HTMLxElement && HTMLxElement.__IElementConstructor ? 
                                     HTMLxElement.__IElementConstructor(el) : el; // hack

    MimicStandardBehavior(newElement);
    //if(tagName === "SCRIPT") {
      //__script.push(el);
    //}

    // build element from faked prototypes
    if (_HTMLElement.__w3c_fake)
      updateObject(newElement, _HTMLElement.prototype);
    if (HTMLxElement && HTMLxElement.__w3c_fake) 
      updateObject(newElement, HTMLxElement.prototype);

    return newElement;
  };

  // mimic standard $root.createEvent()
  //
  $root.createEvent = function (evType) {
    var eo = eventObject();

    if (evType == "MouseEvents" || evType == "MouseEvent")
      eo.initMouseEvent = function (type, canBubble, cancelable, view, 
                     detail, screenX, screenY, clientX, clientY, 
                     ctrlKey, altKey, shiftKey, metaKey, 
                     button, relatedTarget)                 
      {
        var t = this, ievent = t.IEvent;
        t.type = ievent.type = type;
        t.bubbles = canBubble;
        t.cancelable = cancelable;
        t.view = view;
        t.detail = detail;
        t.screenX = screenX;
        t.screenY = screenY;
        t.clientX = clientX;
        t.clientY = clientY;
        t.ctrlKey = ctrlKey;
        t.altKey = altKey;
        t.shiftKey = shiftKey;
        t.metaKey = metaKey;
        t.button = button;
        t.relatedTarget = relatedTarget;
      };

    else if (evType == "KeyboardEvent" || evType == "KeyEvents")
      eo.initKeyEvent = function (type, canBubble, cancelable, view, 
                          ctrlKey, altKey, shiftKey, metaKey, 
                          keyCode, charCode)
      {
        var t = this, ievent = t.IEvent;
        t.type = ievent.type = type;
        t.bubbles = canBubble;
        t.cancelable = cancelable;
        t.view = view;
        t.ctrlKey = ctrlKey
        t.altKey = altKey
        t.shiftKey = shiftKey
        // metaKey is not supported
        t.keyCode = keyCode
        this.charCode = charCode
      };

    else
      eo.initEvent = function (type, canBubble, cancelable)
      {
        var t = this, ievent = this.IEvent;
        t.type = ievent.type = type;
        t.bubbles = canBubble
        t.cancelable = cancelable
      };

    return eo;
  };

  // Refers to the window. 
  // I have no idea why we need yet another reference to the window.
  doc.defaultView = win;

  // styles
  //
  win.getComputedStyle = function(el, smth) {
    var computedStyle = {
      getPropertyValue : function (prop) {
        return el.currentStyle[prop]
      }
    }
    return computedStyle
  };

  // inject methods into all page elements, if needed
  // 
  MimicStandardBehavior.all = function () {
    var all = doc.all;
    for (var i=0; i<all.length; i += 1) {
      MimicStandardBehavior(all[i])
    }
  };

  // externs
  //
  win['w3c'] = MimicStandardBehavior;

  // HTML elements stubs
  var elements = [
    // I copy it from MSDN docs, it may be not full list..
    // uncomment, what you need
    'HTMLElement'
    /*,
    'HTMLAnchorElement',
    'HTMLAreaElement',
    'HTMLBaseElement',
    'HTMLBaseFontElement',
    'HTMLBGSoundElement',
    'HTMLBlockElement',
    'HTMLBodyElement',
    'HTMLBRElement',
    'HTMLButtonElement',
    'HTMLCommentElement',
    'HTMLDDElement',
    'HTMLDListElement',
    'HTMLDTElement',
    'HTMLEmbedElement',
    'HTMLFieldSetElement',
    'HTMLFontElement',
    'HTMLFormElement',
    'HTMLFrameElement',
    'HTMLFrameSetElement',
    'HTMLGenericElement',
    'HTMLHeadElement',
    'HTMLHeadingElement',
    'HTMLHRElement',
    'HTMLHtmlElement',
    'HTMLIFrameElement',
    'HTMLImageElement',
    'HTMLInputElement',
    'HTMLIsIndexElement',
    'HTMLLabelElement',
    'HTMLLegendElement',
    'HTMLLIElement',
    'HTMLLinkElement',
    'HTMLMapElement',
    'HTMLMarqueeElement',
    'HTMLMetaElement',
    'HTMLNextIdElement',
    'HTMLObjectElement',
    'HTMLOListElement',
    'HTMLOptionElement',
    'HTMLParagraphElement',
    'HTMLParamElement',
    'HTMLPhraseElement',
    'HTMLScriptElement',
    'HTMLSelectElement',
    'HTMLSpanElement',
    'HTMLStyleElement',
    'HTMLTableCaptionElement',
    'HTMLTableCellElement',
    'HTMLTableColElement',
    'HTMLTableElement',
    'HTMLTableRowElement',
    'HTMLTableSectionElement',
    'HTMLTextAreaElement',
    'HTMLTitleElement',
    'HTMLUListElement',
    'HTMLDivElement'*/ ];

  for(var i=0; i<elements.length; i++)
    if (!win[elements[i]]) win[elements[i]] = {
        prototype : {},
        __elementName : elements[i],
        toString : function() { return "[object " + this.__elementName + "]"},
        __w3c_fake : true
      };

  _HTMLElement = win["HTMLElement"];

  // jQuery may not work properly if initialized right after that
  //MimicStandardBehavior(win, doc);

})();
/*
 * JooScript foundation: basic code blocks/modules management, types and constructors
 *
 * Copyright (c) 2010 Evgen Burzak <buzzilo at gmail.moc>
 * Released under the MIT/X License
 */

// todo Seal and freeze all internall classes and objects, including globals.

(function() {

  // todo strict mode
  // "use strict"

  // Copy globals and root in this scope
  var glob = $globals, root = $root;

  // Ready flag
  var contentLoaded = false;

  // Set compatibility mode by default in browser
  var compat_mode = typeof $joo_compat !== 'undefined' ? $joo_compat : true;

  // Use runtime typing by default
  var runtime_typing = typeof $use_runtime_typing !== 'undefined' ? $use_runtime_typing : true;

  // Set up basic (primitive) types
  // Some types actually are fake and reserved for possible future
  // todo macro OBJECT, ...
  var OBJECT,
      NUMBER, // real number
      INT,
      UINT,
      FLOAT,
      STRING,
      BOOLEAN,
      FUNCTION,
      CLASS,
      XML,
      NULL, // null 
      VOID, // undefined
      INFINITY, // +/-Infinity
      NAN; // NaN

  OBJECT = 0x1,
  NUMBER = 0x2, 
  INFINITY = NUMBER | 0x80, 
  NAN = NUMBER | 0x100,
  INT = NUMBER | 0x4,
  UINT = NUMBER | 0x8,
  FLOAT = NUMBER | 0x10,
  BOOLEAN = NUMBER | 0x20,
  STRING = 0x40,
  FUNCTION = OBJECT | 0x200,
  CLASS = OBJECT | FUNCTION | 0x400,
  XML = OBJECT | 0x800,
  VOID = 0x1000,
  NULL = 0x2000; // XXX is the null an object??? In JS it is ...

  // Save the JS Number
  var JSNumber = Number, 
      JSString = String, 
      JSBoolean = Boolean, 
      JSObject = Object,
      JSFunction = Function;

  var _Object = JSObject,
      _Function = JSFunction;

  function _String(x){
    x = new JSString(x === undefined ? "" : x)
    x.__type__ = _String.type << 16 | STRING | OBJECT
    x.__class__ = _String
    return x
  }

  _String.fromCharCode = JSString.fromCharCode

  function _Boolean(x){
    x = new JSBoolean(x === undefined ? false : x)
    x.__type__ = _Boolean.type << 16 | BOOLEAN | OBJECT
    x.__class__ = _Boolean
    return x
  }

  // With object's valueOf(), math operations is so so slow ...

  // todo size conversion
  // fixme Infinity type
  // size can be 8, 16, 32 for Int, Uint and 32, 64 for float
  function _Float (x, size){ 

    x = JSNumber(x === undefined ? 0 : x)
    // infinity
    if( x == Infinity || x == -Infinity ) {
      x = new JSNumber(x); 
      x.__type__ = INFINITY
    // just a number
    } else if( x === x ) {
      x = new JSNumber(x); 
      x.__type__ = FLOAT;
    // NaN is always not equal to self
    } else {
      x = new JSNumber(NaN); 
      x.__type__ = NAN
    }

    x.__type__ |= _Float.type << 16 | OBJECT;
    x.__class__ = _Float

    return x
  }

  // Integer number
  function _Int (x, size){ 

    x = JSNumber(x === undefined ? 0 : x)
    // infinity
    if( x == Infinity || x == -Infinity ) {
      x = new JSNumber(x); 
      x.__type__ = INFINITY
    // just a number
    } else if( x === x ) {
      x = new JSNumber(x | 0); 
      x.__type__ = INT;
    // NaN is always not equal to self
    } else {
      x = new JSNumber(NaN); 
      x.__type__ = NAN
    }

    x.__type__ |= _Int.type << 16 | OBJECT;
    x.__class__ = _Int

    return x
  }

  // fixme Infinity type
  function _Uint (x, size){ 

    x = JSNumber(x === undefined ? 0 : x)
    // infinity
    if( x == Infinity || x == -Infinity) {
      x = new JSNumber(x); 
      x.__type__ = INFINITY
    // just a number
    } else if( x === x ) {
      x = new JSNumber(Math.abs(x | 0)); 
      x.__type__ = UINT;
    // NaN is always not equal to self
    } else {
      x = new JSNumber(NaN); 
      x.__type__ = NAN
    }

    x.__type__ |= _Uint.type << 16 | OBJECT;
    x.__class__ = _Uint

    return x
  }

  // In JooScript Number has the same name,
  // Number is a real number
  function _Number(x) {

    x = new JSNumber(x === undefined ? 0 : x)
    x.__type__ = ( x == Infinity || x == -Infinity ? INFINITY :
                    // NaN is always not equal to self
                    x+0 === x+0 ? NUMBER : NAN ) | _Number.type << 16 | OBJECT;
    x.__class__ = _Number

    return x
  }

  _Number.prototype =
  _Float.prototype = 
  _Int.prototype = JSNumber.prototype
  _String.prototype = JSString.prototype
  _Boolean.prototype = JSBoolean.prototype

  // XXX huh?
  function _Null (){ return null }
  function _Void (){ return undefined }

  _Number['new'] = 
  _Float['new'] = 
  _Int['new'] = 
  _String['new'] = 
  _Boolean['new'] = 
  _Null['new'] = 
  _Void['new'] = function (x, y){
    return this(x, y)
  }

  // huh? Float should be converted into fixed value, but toString not works!
  /*
  if( !compat_mode ) {
    JSNumber.prototype.__toString__ = JSNumber.prototype.toString
    JSNumber.prototype.toString = function(){
      return this.__type__ & FLOAT ? this.toFixed(1) : this.__toString__()
    }
  }
  */
  
  // all imported symbols will be stored in an unique namespace, not in
  // window object, for not making names hell
  var groupsNS = "$groups",
      ns_slash = ".",
      slice = Array.prototype.slice,
      last = function () { return this[this.length - 1]; },
      _event = _Event();

  // Exceptions
  //
  function ImportError(msg) {
    this.message = msg
  }

  ImportError.prototype = new Error;

  function _Error(msg) {
    return Error(msg)
  }

  function typeError(msg) {
    throw TypeError(msg)
  }

  // Workaround for JavaScript design flow: object notations {"key":"abc"} and {key:"abc"} 
  // have the same meanings.
  // Usage:
  //   dict([['two', 3], ['one', 2]])
  //   dict({'one': 2, 'two': 3})
  //   dict(zip(['one', 'two'], [2, 3]))

  // todo
  function dict(args) {
    // dict() is an python-like object constructor for pairs [key, value], where key is a variable.
    // input arguments are pairs [[key, value], [key, value], ...] or object {one: 2}
    //
    // Firefox has a bug: inside the loop, arguments[0] are always = 0, that's workaround
    //var args = slice.call(arguments, 0);
    var _dict = {};
    for(var i=0;i<args.length;i++) {
      _dict[args[i][0]] = args[i][1];
    }
    return _dict;
  };

  // todo
  function zip() {};

  // package constructor
  function _Package (groupNamespace, packageBody) {
    var ns = groupNamespace.split(ns_slash),
        group = getGroupObject(ns);

    packageBody.call(group, group);
  };

  // The group constructor

  function _Group (groupName) {
    this.__groupToken__ = groupName;
  };

  _Group.prototype = {
    "__groupToken__" : null
  };

  var internalObjectProps = {
    '__proto__' : null,
    '__class__' : null,
    '__type__' : null
  }

  function extendObject(obj, addMe, except) {
    if( except === undefined ){
      except = internalObjectProps;
    }
    for( var x in addMe ) {
      if( except[x] === undefined )
      {
        obj[x] = addMe[x];
      }
    }
    return obj
  }; 

  // Class roaster
  var classes = [];

  // That will initialize a class 
  //
  function initClass( _class )
  {
    //trace("initClass()", _class)

    buildDescendant( _class );

    // apply class body
    _class.classBody.call( _class.prototype, _class )

    // call init callback
    if( testType( _class.__init__ ) & FUNCTION )
      _class.__init__();
  }

  // This builds descendant from class ancestors,
  // algorithm is fairy straightforward and it should be extended somehow ..
  function buildDescendant(_descendant, _class, _incStack){
    //if(!_incStack) _incStack = [];
    //trace("buildDescendant("+[_descendant, _class]+")")
    if(!_class) _class = _descendant
    var ancestors = _class.ancestors, ancestor;
    for (var i=0; i<ancestors.length; i++) 
    {
      ancestor = ancestors[i]
      if( isVoid( ancestor ) ) 
        throw new Error("Undefined ancestor in class " + _descendant.className);

      // fixme it *may* fall into eternal recursion!
      // start from descendants of ancestors of 
      // descendant of ancestors of ... <recursively>
      if( ancestor != _descendant && 
          ancestor != _class )  // prevent eternal recursion
      {
        buildDescendant( _descendant, ancestor, _incStack )
      }

      // apply class body of ancestor on descendant
      ancestor.classBody.call(_descendant.prototype, _descendant)
      if( ancestor.className ) 
        // add link to ancestor by class name
        _descendant.ancestors[ancestor.className] = ancestor;
    }
  }

  // This method calculated parent of the function, 
  // note that parent is a class instance , not a function
  function getParent(_fun){
    var i=0;
    var caller = _fun.caller || _fun.__caller__; // workaround for safari/iphone
    var parent = null
    while(caller) {
      if(caller.__owner__) {
        parent = caller.__owner__
        break
      }
      caller = caller.caller;
      // if no caller with __owner__ is defined, it may make eternal loop in some cases
      if(i>1000) {/*trace("Too much recursions in ", caller);*/parent=null;break;}
      i++
    }
    return parent;
  }

  /*
  function matchClassRole( _class, spec ){
    // check class for role characteristics, raise error if some properties are missing
    if( spec ) {
      if( isVoid( _class.role.match( spec ) ) ) {
        throw ClassError(_class.className + " does not match the role" )
      }
    }
  }
  */

  function classBodyStub(){}

  // $buildClass() builds classes in pythonic style.
  //
  // Structure of class object:
  //
  // Class
  //   ├───── className String
  //   ├───── prototype Class
  //   ├───── ancestors Array
  //   ├───── role Role, class spec
  //   ├───── new(), class constructor
  //   ├───── __init__(), init callback
  //   └───── classBody(), class body
  //
  // Structure of class instance:
  //
  // self
  //   ├───── __class__ ClassWrapper
  //   └───── parent Class, parent instance
  //
  // Note for me: class builder must not care about duplicates and such things, it's compilers 
  // work to handle these mistakes.
  //
  // todo emulate private member with __defineGetter/Setter__: throw error if 
  // caller.caller.__owner__ of getter/setter !== member.__owner__
  // fixme But it is really a need? All props are freely available in a class prototype...
  //
  function buildClass (className, ancestors, classBody, spec) 
  {
    // Be carefull, vertigo beginning ...

    // create a class wrapper
    // it returns just an object if caller is constructor and class instance in 
    // any other case
    function anonymous(context){
      // it is a hack for cases when result of `x instanceof y` is critical even if 
      // a script executed in IE,
      if( context === anonymous ) return this
      else return anonymous['new'].apply(anonymous, arguments)
    }

    // set up a class as instance of the Class
    anonymous.prototype = new _Class

    // set class name
    anonymous.className = className;

    // set class body or body stub
    anonymous.classBody = classBody || classBodyStub;

    // set class ancestors
    anonymous.ancestors = []

    // set the class spec
    anonymous.role = _Role()

    // fill ancestors from arguments
    if( ancestors && ancestors.length>0 ) {
      for( var i=0; i<ancestors.length; i++ ) {
        if( isClass( ancestors[i] ) ) {
          anonymous.ancestors[i] = ancestors[i]
          anonymous.role.inherit( ancestors[i].role )
        }
        else {
          typeError(ancestors[i] + " is not a class")
        }
      }
    }

    // todo check prototype after that
    anonymous.role.inherit( spec || {} )

    // initialization routines
    function init(){
      //trace("initialize", anonymous.className)
      initClass( anonymous )
      // do not set constructor until class is not initialized
      anonymous['new'] = classConstructor;
    }

    // initialize class on global event
    _event.once("initialize", init)

    // register class in global class storage and change type of the function
    registerClass( anonymous )
    
    // ... or immediately if content was loaded
    if( contentLoaded ) init()

    // replace toString with handy decorator
    anonymous.toString = classToString

    return anonymous;
  };

  var cachedMethods = {};

  function getRandomName() {
    return "$"+Math.round(Math.random()*1000000).toString(33)
  }

  // It's bind a method to a class instance.
  // Using wrapped methods (class only) enables me to implement type checking and
  // rest argument in plain JS.
  function wrapInstanceMethod(_class, instance, name, returnType, argsType){
    var cacheName = _class.type + "-" + name
    var cachedWrapper = cachedMethods[cacheName]
    var proto = _class.prototype
    var fun = proto[name]
    // fixme check for changes in returnType and argType
    if( cachedWrapper === undefined || cachedWrapper.fun !== fun ) {
      var _typeError = getRandomName()
      var _typeErrMsg = getRandomName()
      var fstr = fun.toString();
      var _args = fstr.replace(/\/\*.*\*\//g, "") // clear inline comments
                      .match(/function(\s+)?([a-zA-Z\$_0-9]+)?(\s+)?\(([a-zA-Z\$_0-9,\s]+)\)/);
      var args, _self, last, rest, restAt;
      var typedArgs = "", typeClass, _argType, argsLen = 0;
      if( _args && _args.length>1 ) {
        // arguments, array
        _args = _args[4].replace(/\s+/g, "").split(",")
        // arguments length, shift context
        argsLen = _args.length-1
        // arguments, string
        args = slice.call(_args, 1).join(",");
        // context 
        _self = _args[0];

        if( argsType.length ) {
          typedArgs = []
          typeClass = []
          for( var i=1; i<_args.length; i++ ) 
          {
            // shift "self"
            _argType = argsType[i-1]

            // pass if argument type is null or undefined
            if( isVoid(_argType) ) {
              typedArgs[i-1] = _args[i]

            // fixme test NAN and INFINITY
            } else if( _argType.__type__ & NUMBER ) {
              typedArgs[i-1] = _args[i] + ".__type__ & " + (_argType+0) + " ? " 
                                + _args[i] + " : " 
                                + _typeError + "("+_typeErrMsg+")";

            // for a class, test will be a bit different
            } else if( isClass(_argType) ) {
              // high fields of __type__ is a flags of basic types,
              // low bits is a custom type, so we need to check whether second half
              // bits is equal to class type
              // fixme i'm not sure it's a good idea, because i'm hurry ...
              //       what if instead of comparing numbers, just compare arg.__class__ and argType??
              typedArgs[i-1] = _args[i] + ".__class__.type === " + (_argType.type) + " ? " 
                                + _args[i] + " : " 
                                + _typeError + "("+_typeErrMsg+")";

            } else
              typeError("argument type is not a number or a class")
          }
        } else {
          typedArgs = args
        }
        last = _args[_args.length - 1]
        // fixme probleme with GCC
        if(last == "__rest__") {
          rest = "__rest__";
          restAt = _args.length-1
        }
      } else {
        args = "";
        _self = "self";
      }
      // prevent argument subtitutes
      var i = getRandomName()
      var _proto = getRandomName()
      //var _self = "self"

      // build test for return type
      var testReturnType;
      if( isVoid( returnType ) )
        testReturnType = ""
      else if( returnType & ( NULL | VOID ) )
        testReturnType = _self + " === null || " + _self + " === undefined"
      // fixme test NAN and INFINITY
      else if( returnType.__type__ & NUMBER )
        testReturnType = _self + ".__type__ & " + (returnType+0)
      else if( isClass( returnType ) )
        testReturnType = _self + ".__class__.type === " + (returnType.type)
      else {
        typeError("return type is not a number or a class")
      }

      // I'll inlining a wrapper stuff for fast calls
      var body =
      [ argsType.length ? "var "+_typeErrMsg+"='argument type does not match a class spec';" : "", 
        "return function(",args,") {",
          // 'rest' argument will contain all arguments after rest keyword, 
          // a similar syntax used in AS, e.g. function test(x, y, ...args)
          rest ? ["if(arguments.length>=",restAt,"){",
            rest,"=[arguments[",restAt-1,"]];",
            "for(var ",i,"=",restAt,";",i,"<arguments.length;",i,"++)",
              rest, "[",i,"-",restAt-1,"]=arguments[",i,"];} else "
          ].join("") : "",

          // check arguments list
          "if(arguments.length !== ",argsLen,")",
            _typeError,"('",name," takes exactly ",argsLen," arguments ",
                          "('+arguments.length+' given)');",

          // replace self with return value
          returnType ? _self + "=" 
                     : "return ",

          // call wrapped function from prototype object,
          // also check argument types if required
          _proto, ".",name,"(",_self, typedArgs.length ? [",",typedArgs].join("") : "",")",

          // test returned type if required
          testReturnType ? ";return " + testReturnType + "?" + _self + ":" + _typeError 
                          + "('return type does not match a class spec')" : "",

      "}"].join("");

      cachedWrapper = 
      cachedMethods[cacheName] = Function(_self, _proto, _typeError, body)
      cachedWrapper.fun = fun
    }
    //else trace("hit cache", cacheName)
    // evaluate the function wrapper
    var wrapper = cachedWrapper(instance, proto, typeError);
    wrapper.__name__ = name
    // it seems that __parent__ are reserved object property in Firefox...
    wrapper.__owner__ = instance;
    wrapper.__func__ = fun;
    wrapper.toString = funToString;
    return wrapper
  }

  // This makes an class instance. If browser is supported ECMAScript 5, then 
  // class props will be defined with object descriptors
  // todo getters and setters
  function classConstructor() {
    var _class = this
    var args = arguments
    var instance = new _class(_class, args) 
    var proto = _class.prototype
    // fix for IE
    if( !instance.__proto__ )
      instance.__proto__ = proto
    // constructor have to be defined in class spec
    // fixme maybe make chain of constructors?
    var constructor = null
    var constructors = 0
    if( _class.role ) {
      for( var prop in _class.role ) {
        if( prop in roleExcept ) continue
        // raise an error if class missed spec property
        if( proto[prop] === undefined ) {
          throw _Error(_class.className + " does not match the class role")
        }
        var spec = _class.role[prop]
        if( spec ) {
          // use spec value as a type if it a number
          var type = !isNaN(spec) && spec+0 || spec.type || 0
          // we have to rebuild a spec, because if some fields are missed, it will be 
          // set with default values which is false, but we need a true,
          // field 'internal' has higher priority than others
          spec = {
            writable: spec.internal === undefined ? 
              spec.frozen === undefined ? 
                spec["public"] === undefined ? true : spec["public"] :
                !spec.frozen : 
              !spec.internal,
            configurable: spec.internal === undefined ? 
              spec.sealed === undefined ? 
                spec["public"] === undefined ? true : spec["public"] :
                !spec.sealed : 
              !spec.internal,
            enumerable: spec.internal === undefined ? 
              spec.hidden === undefined ? 
                spec["public"] === undefined ? true : spec["public"] :
                !spec.hidden : 
              !spec.internal,
            // use spec value as a type 
            type: !isNaN(spec) && spec+0 || spec.type || 0,
            // fixme object has constructor property which is a function Object!
            constructor: typeof spec.constructor === "function" ?  
              false : spec.constructor,
            returnType: spec.returnType,
            // argumentType is an array with length equal to arguments length
            argumentType: spec.argumentType
          }
          // raise an error if at least one object descriptor is defined , but not supported 
          if( !ecmascript5compliant ) {
            if( spec.writable + spec.configurable + spec.enumerable < 3 )
              throw _Error("browser is not ECMAScript 5 compliant. Please upgrade your browser!")
          }
          // of if the type of a prop is set and not null ...
          if( type ) {
            // skip classes
            if( (type ^ FUNCTION) & CLASS ) { 
              spec.value = proto[prop]
            }
            // type is required for functions, or it will be plain
            else if( type & FUNCTION ) { 
              // wrap the function ... 
              spec.value = wrapInstanceMethod(_class, instance, prop, 
                            runtime_typing && spec.returnType || null, 
                            runtime_typing && spec.argumentType || [])
              // define class constructor
              if( spec.constructor ) {
                if( !constructors ) {
                  constructor = spec.value
                  constructors += 1
                }
                else {
                  throw _Error(_class.className + " has multiple constructors at once")
                }
              }
            }
          }
          else 
            spec.value = proto[prop]

          // define property as object descriptor if supported
          if( ecmascript5compliant )
            defineProperty(instance, prop, spec)
          else
          // fallback for others
            instance[prop] = spec.value
        }
      }
    }
    // set parent class of the instance
    instance.parent = getParent(classConstructor)
    // set backlink to the __class__ (it's similar to __proto__ property)
    // todo it should be not enumerable? In old IEs it will be visible ...
    instance.__class__ = _class
    // call actual class constructor
    var newObject = null
    if( testType( constructor ) & FUNCTION 
          && constructor !== _class   
          && constructor !== JSObject
    ) {
      newObject = constructor.apply(instance, args)
    }
    // this behavior reflects  'new' JS constructor which can return
    // any object, not only an object instance
    return testType( newObject ) & OBJECT ? newObject : instance;
  };


  // todo make it similar to Function():
  // Class(ancestor1, ancestor2, ..., body)
  function _Class (){
    //var ancestors = slice.call(arguments, 0, arguments.length-2),
    //    body = arguments[arguments.length-1];
  };

  _Class.prototype = {
    "__class__" : null,
    "parent" : null,
    "toString" : function(){
      return this.__str__ ?  this.__str__() :
        ["[class ", (this.__class__ && this.__class__.className) || "Anonymous","]"].join("");
    }
  }

  _Class['new'] = classConstructor

  function testType( value ) {

    if( value === undefined ) return VOID

    else if( value === null ) return NULL

    //else if( !isVoid( value.__type__ ) ) {
    else if( !( value.__type__ === undefined || value.__type__ === null )  ) {

      return value.__type__;

    } else {

      var t = typeof value

      switch(t) {
        case "number": 
          return NUMBER
        case "string": 
          return STRING
        case "function": 
          return FUNCTION
        case "boolean": 
          return BOOLEAN
        case "object": 
          return OBJECT
      }
    }
  };

  function getClassOf(x){
    var t = testType(x)
    if( ! ( t & OBJECT ) ) typeError(x + " is not an object")

    // order have matter!
    return ( isClass( x.__class__ ) ? x.__class__ :
             // fixme is it required?
             t & INT ^ NUMBER ? _Int :
             t & UINT ^ NUMBER ? _Uint :
             t & FLOAT ^ NUMBER ? _Float :
             t & BOOLEAN ^ NUMBER ? _Boolean :
             t & NUMBER ? _Number :
             t & STRING ? _String :
             t & FUNCTION ? _Function :
             t & CLASS ? _Class :
             t & XML ? _XML :
             t & OBJECT ? _Object :
             null );
  };

  function funToString() {
      // Stack overflow in IE at this line
      return "function wrapped(){/*stub*/}"
    //return this.type === FUNCTION ? this.__func__.toString() : this.toString();
  };

  function getFunctionName(fun){
    var m = fun.toString().match(/function(\s+)?([a-zA-Z\$_0-9]+)?/)
    return (m && m[2]) || null
  }

  function classToString(){
    return ["class ",(this.className || "Anonymous"),"(...)"].join("") 
  }

  // registerClass() registered classes in global class roaster and
  // converts a function into a "class"
  function registerClass(_class) {
    //trace("registerClass()", _class, classId)

    var classType

    if( !isVoid( _class.type ) )
      classType = _class.type

    // get unqiue type id for this class
    else if( isVoid( classType ) )
      classType = getTypeId()

    if( !isVoid( classes[classType] ) )
      throw Error("A class has already registered in the roaster")

    // _class is a function, so convert the function into the class
    if( testType( _class ) === FUNCTION ) {
      var class_prototype = _class.prototype
      // set class name from function name
      if( !_class.className ) {
        _class.className = getFunctionName(_class)
      }
      // add backlink to prototype
      class_prototype.__class__ = _class
      // fix __proto__ for IE
      if( isVoid( class_prototype.__proto__ ) ) {
        class_prototype.__proto__ = class_prototype
      }
      // create empty class spec
      if( ! _class.role ) {
        _class.role = _Role()
      }
      // static 'new' method must be attached in class builder, or manually,
      // because of some classes are using customized constructors 
      // (plain function for example)

      // set type id for class object as CLASS,
      // until that __type__ was FUNCTION
      _class.__type__ = CLASS;

      // set unique class id
      _class.type = classType
    }

    // add object to roaster
    classes[classType] = _class
  }

  function registerClasses() {
    for(var i=0; i<arguments.length; i++){
      registerClass(arguments[i])
    }
  }

  _Class.registerClass = registerClass
  // fixme maybe leave only registerClasses?
  _Class.registerClasses = registerClasses

  // Type validators

  // todo macro function isVoid ...
  function isVoid (x) { return x === undefined || x === null }

  // Read me:
  // http://ejohn.org/blog/objectgetprototypeof/
  //
  // IE suck at this point ... 
  var getPrototypeOf = typeof Object.getPrototypeOf === "function" ? 
                              Object.getPrototypeOf :
                              function(x){ 
                                if( !( testType(x) & OBJECT ) ) 
                                  typeError("x is not object");

                                return typeof x.__proto__ === "object" ? x.__proto__ :
                                        // fallback for other
                                        Object.prototype;
                              };

  // IE suck again, defineProperty does not work with simple objects, only with
  // DOM nodes
  var defineProperty = typeof Object.defineProperty === "function" ?
                              Object.defineProperty : 
                              function(){}; // silent fallback
                              
  // to be sure platform is ECMAScript 5 compliant ...
  // todo extend with all tests, http://kangax.github.com/es5-compat-table/
  // todo conformance tests
  var ecmascript5compliant = 
      (function(){
        // test will fail in IE8 due to defineProperty only accepts DOM objects
        try {
          var testObject = {}
          // set property spec 
          var spec = {
            value: 1,
            writeable: false,
            enumerable: false,
            configurable: false
          }
          defineProperty(testObject, "x", spec)
          // x was defined with value field, it should be 1
          if( testObject.x === undefined ) {
            return false
          }
          // prop x must not be writable 
          testObject.x = 2
          if( testObject.x === 2 ) {
            return false
          }
          // prop x must not be configurable
          delete testObject.x
          if( testObject.x === undefined ) {
            return false
          }
          // prop x must be hidden
          for( var prop in testObject)  {
            if(prop === "x") 
              return false
          }
          // all ok!
          return true
        } catch(e) {
          return false
        }
      })();

  // todo isPrimitive (new Number(123)) returns true
  function isPrimitive (x) { 
    // Convert type errors into the false
    try{
      return getPrototypeOf(x) === Object.prototype
    }catch(e){
      // todo test type of primitive value
      return false
    } 
  }

  // so that classes cannot be faked ...
  function isClass (x) { 
    return !isVoid(x) && classes[x.type] === x;
  }

  function is_a (x, c) { 
    // translate getClassOf() exceptions into false
    try {
      return isClass(c) ? getClassOf(x) === c : false;
    }catch(e){
      // todo test primitive type
      // if( testType( x ) === STRING && c === _String ) return true
      // if( isPrimitive( x ) && x instanceof c ) return true
      return false
    }

    /*
    if( c.__type__ === CLASS && isClass(x) ) 
      return true;
    // hmmm... is a fake?
    if( x instanceof _Class && !isClass(c) ) 
      return false;
    return testType(x) === c.__type__;
    */
  }

  function isObject(x) { 
    return !!( testType( x ) & OBJECT );
  }

  // Basic JooScript module aka Unit.
  // Unit is related to the file, where it is declared. 
  //
  function _Unit(path, file, module){
    // todo extend me with handy exceptions, ... 
    var unit = _Namespace()
    // Import Joo basics into unit namespace
    _Import(unit, "joo.*")
    unit.__path__ = path
    unit.__file__ = file
    module.call(unit, unit, root, glob)
  }

  // Import
  function _Import (context) {
    var ns_s, ns_a, ns, symbolName, current,
        args = slice.call(arguments, 1);

    // if context is omit, assumed context is this context
    // so that ...
    // >>> $Import("org.mygroup")
    // >>> inst = mygroup.MyClass['new']()
    //
    if(typeof context == "string") {
      args = slice.call(arguments, 0)
      context = this;
    }

    for ( var i=0; i<args.length; i++ ) {
      ns_s = args[i]
      ns_a = ns_s.split(ns_slash)
      symbolName = last.call(ns_a)
      ns = symbolName == "*" ? slice.call(ns_a, 0, ns_a.length-1) : ns_a;
      //trace("ns " + ns + "; " + symbolName)
      try {
        current = getGroupObject(ns)
      } catch (e) {
        throw Error(e.message + " in " + ns_s)
      }
      
      if (symbolName === "*") {
        extendObject(context, current, _Group.prototype);
      } else {
        context[symbolName] = current
      }
    }

    return context;
  };

  function ImportFrom (module, from) {
    // todo
  };

  // getGroupObject build and return a group namespace,
  // or raise error if ns is read only and no ns token is defined
  function getGroupObject (ns, readOnly) {
    var parent = glob[groupsNS],
        symb = parent, 
        token, i;

    if (ns.length == 1 && !ns[0]) { return symb }

    for(i=0; i < ns.length; i++) {
      token = ns[i]
      if(!parent.__groupToken__) 
        throw Error("Token '" + token + "' is not group token");
      symb = parent[token]
      if (typeof symb == "undefined") {
        if (readOnly) 
          throw Error("Token " + token + " not found")
        else {
          symb = parent = parent[token] = new _Group(token);
        }
      } else if (i == ns.length-1) {
        break
      } else {
        parent = symb
        symb = parent[token]
      }
    } 
    
    return symb;
  };

  // todo type casting (is it possible?)
  //
  function _Type(value, type) {
    if(!arguments.length)
      throw Error("Type is not constructor!")
  };

  var lastClassId = 0

  function getTypeId () {
    return (++lastClassId)
  }

  _Type.getTypeId = getTypeId

  // Role constructor
  //
  function _Role( spec, proto ) {
    if(_Role.caller === _Role) return this;
    var role = new _Role;
    if( proto ) {
      role.inherit( proto )
    }
    if( spec ) {
      role.inherit( spec )
    }
    return role;
  };

  _Role.type = getTypeId()

  _Role.prototype = {
    // check for matching an object with the role
    'match' : function( spec ){
      if( !( testType( spec ) & OBJECT ) ){
        typeError(spec + " is not an object")
      }
      return matchRole(this, spec)
    },
    'inherit' : function( spec ){
      if( !( testType( spec ) & OBJECT ) ){
        typeError(spec + " is not an object")
      }
      extendObject(this, spec, roleExcept)
    },
    "__type__" : _Role.type << 16 | OBJECT
  }

  var roleExcept = {}
  extendObject( roleExcept, internalObjectProps, {} )
  extendObject( roleExcept, _Role.prototype )

  // Matching object with a spec
  function matchRole(spec, obj){
    for( var prop in spec ) {
      if( prop in roleExcept ) continue;
      //trace(prop, typeIdToStr(testType(obj[prop])), isVoid( obj[prop] ) )
      if( isVoid( obj[prop] ) )
        return null
    }
    return obj
  }

  _Role.match = matchRole

  // VectorArray is a wrapper for TypedArray:
  // Spec: https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/TypedArray-spec.html
  // Worth reading: 
  // 1. https://developer.mozilla.org/en/JavaScript_typed_arrays
  // 2. https://developer.mozilla.org/en/JavaScript_typed_arrays/ArrayBufferView
  // 
  // Args:
  // init {array or number}: default is 0
  // size {int, uint, float}: default is Int(32), can be Int(8), Int(16), Float(32) etc..
  function _VectorArray(init, size) {

    if( isVoid( init ) ) init = 0
    if( isVoid( size ) ) size = _Int(32)

    // fallback to untyped array
    if(typeof ArrayBuffer === 'undefined') {
      var view = typeof init === 'object' ? init : new Array(init);
      view.buffer = view;
      view.set = function(src) {
        for(var i=0; i<view.buffer.length; i++)
          view.buffer[i] = src[i]
      }
      return view;
    }

    //trace(init, size)

    var len = testType(init) == OBJECT ? init.length : init,
        buffer = new ArrayBuffer(len * size);

    var elType = testType( size ) ^ NUMBER;

    var typeArray, view;

    if(elType & INT && size+0 == 8)
      typeArray = Int8Array;
    else if(elType & UINT && size+0 == 8)
      typeArray = Uint8Array;
    else if(elType & INT && size+0 == 16)
      typeArray = Int16Array;
    else if(elType & UINT && size+0 == 16)
      typeArray = Uint16Array;
    else if(elType & INT && size+0 == 32)
      typeArray = Int32Array;
    else if(elType & UINT && size+0 == 32)
      typeArray = Uint32Array;
    else if(elType & FLOAT && size+0 == 32)
      typeArray = Float32Array;
    else if(elType & FLOAT && size+0 == 64)
      typeArray = Float64Array;
    else
      throw new Error("VectorArray: syntax error");

    view = new typeArray(buffer, 0, len)

    if(testType(init) == OBJECT) {
      view.set(init)
    }

    return view;
  }

  // Namespace constructor
  //
  function _Namespace(prefix, uri) {
    if( _Namespace.caller === _Namespace ) return this
    var ns = new _Namespace;

    if( arguments.length == 1 )
      uri = prefix,
      uri = undefined;

    ns.prefix = prefix
    ns.uri = uri

    return ns
  };

  // todo inline XML, based on E4X spec
  // http://www.ecma-international.org/publications/standards/Ecma-357.htm
  function _XML() {
    var args = slice.call(arguments, 0),
        xml = args.join("");
  };

  glob[groupsNS] = {}; glob[groupsNS].__groupToken__ = "root";

  // make system methods available elsewhere
  // 
  glob["$Unit"] = _Unit,
  glob["$Package"] = _Package,
  glob["$Import"] = _Import,
  glob["$ImportFrom"] = ImportFrom,
  glob["$Event"] = _Event,
  glob["$buildClass"] = buildClass;

  if( !compat_mode )
    _Object.extend = extendObject;

  if(typeof _Object.getPrototypeOf !== "function")
    _Object.getPrototypeOf = getPrototypeOf;

  if(typeof _Object.getClassOf !== "function")
    _Object.getClassOf = getClassOf;

  // In compatible mode, main internal classes will not be published 
  // in global object. This is helpful in cases when used in parallel with jQuery, MooTools and others...
  if(!compat_mode)
    glob["Number"] = _Number, 
    glob["Float"] = _Float, 
    glob["Int"] = _Int, 
    glob["Uint"] = _Uint, 
    glob["Boolean"] = _Boolean, 
    glob["String"] = _String, 
    glob["VectorArray"] = _VectorArray, 
    glob["Null"] = _Null, 
    glob["Void"] = _Void,
    glob["Role"] = _Role,
    glob["Class"] = _Class,
    glob["Type"] = _Type;

  // Firefox has ECMA XML extension support
  if(!glob["XML"])  {
    if(!compat_mode) {
      glob["XML"] = _XML,
      glob["Namespace"] = _Namespace;
    }
  }

  if(typeof window != "undefined")
    glob["$window"] = window
  if(typeof document != "undefined")
    glob["$document"] = document
  
  // Bind validators to the Type object
  _Type.isVoid = isVoid
  _Type.isPrimitive = isPrimitive
  _Type.isClass = isClass
  _Type.isObject = isObject
  _Type.is_a = is_a
  // Yay! In JooScript typeof is deprecated!
  _Type.getTypeOf = testType

  _Type.NUMBER /*= _Number.prototype.__type__   */  = NUMBER
  _Type.INT    /*= _Int.prototype.__type__   */     = INT
  _Type.UINT   /*= _Uint.prototype.__type__   */    = UINT
  _Type.FLOAT  /*= _Float.prototype.__type__ */     = FLOAT
  _Type.BOOLEAN/*= _Boolean.prototype.__type__*/    = BOOLEAN
  _Type.STRING /*= _String.prototype.__type__ */    = STRING
  _Type.VOID   /*= _Void.prototype.__type__  */     = VOID
  _Type.NULL   /*= _Null.prototype.__type__  */     = NULL
  _Type.OBJECT /*= _Object.prototype.__type__ */    = OBJECT
  _Type.FUNCTION /*= _Function.prototype.__type__*/ = FUNCTION
  _Type.CLASS  /*= _Class.prototype.__type__ */     = CLASS
  _Type.XML    /*= _XML.prototype.__type__   */     = XML
  _Type.NAN                                         = NAN
  _Type.INFINITY                                    = INFINITY

  if(!compat_mode)
    JSObject.prototype.__type__ = OBJECT,
    JSFunction.prototype.__type__ = FUNCTION;

  // very a few programs using this feature, so it is safe to define 
  // type of strings and numbers
  JSString.prototype.__type__ = STRING
  JSBoolean.prototype.__type__ = BOOLEAN
  JSNumber.prototype.__type__ = NUMBER

  var joo_base;

  // pack it all into base package
  _Package("joo", function(joo_base_){
    joo_base = joo_base_
    joo_base_.Number = _Number
    joo_base_.Float = _Float
    joo_base_.Int = _Int
    joo_base_.Uint = _Uint
    joo_base_.Null = _Null
    joo_base_.Void = _Void
    joo_base_.Object = _Object
    joo_base_.Boolean = _Boolean
    joo_base_.String = _String
    joo_base_.VectorArray = _VectorArray
    joo_base_.Type = _Type
    joo_base_.Role = _Role
    joo_base_.Import = _Import
    joo_base_.ImportFrom = ImportFrom
    joo_base_.Package = _Package
    joo_base_.Unit = _Unit
    joo_base_.Namespace = _Namespace
    joo_base_.Group = _Group
    joo_base_.Function = _Function
    joo_base_.Class = _Class
    joo_base_.XML = _XML
    joo_base_.Event = _Event
    joo_base_.buildClass = buildClass
  });

  _Package("joo.object", function(obj){
    obj.extend = extendObject
    obj.dict = dict
    obj.zip = zip
  });

  _Package("platform", function(platform){
    platform.ecmascript5compliant = ecmascript5compliant
  });

  // if no compat mode, add Joo base to the object prototype 
  // to make fast access to basic methods without scope queries
  // 
  // fixme jQuery fall down into eternal recursion with this!
  //if( !compat_mode)
    //JSObject.prototype.__joo__ = joo_base;

  // run initialization routines when content was loaded
  _event.once("contentloaded", function(){
    contentLoaded = true;
    _event.dispatch("initialize")
  });

  // Register internal classes
  //
  (function(){
    var cl;
    for(var i=0; i<arguments.length; i++) {
      cl = arguments[i]
      registerClass(cl);
    }
  })( _Number, _Int, _Uint, _Float, _String, _Boolean, _Function, _Null, _Void,
       _Class, _Namespace, _XML, _VectorArray, _Event);

  // debug helpers

  /* fixme
  var type2str;
  function typeIdToStr(id){
    if( !type2str ){
      type2str = []
      for(var t in _Type) {
        if(typeof _Type[t] == "number" && t != 'lastId') type2str[_Type[t]] = t;
      }
    }
    return type2str[id]
  }
  */


  // delete imported symbols on unload in IE to avoid memory problems
  //
  function clearSymbols() {
    $globals.detachEvent("onbeforeunload", clearSymbols);
    // delete class storage
    classes = null
    // clear cache
    cachedMethods = null
    // delete imported symbols
    $globals[groupsNS] = null
    // and all internals
    if(!compat_mode)
      glob["Number"] = 
      glob["Float"] = 
      glob["Int"] = 
      glob["Uint"] = 
      glob["Boolean"] = 
      glob["String"] = 
      glob["VectorArray"] = 
      glob["Null"] = 
      glob["Void"] = 
      glob["Role"] = 
      glob["Class"] = 
      glob["Type"] = 
      glob["dict"] = 
      glob["zip"] = null;
      
    glob["$Unit"] = 
    glob["$Package"] = 
    glob["$Import"] = 
    glob["$ImportFrom"] = 
    glob["$Namespace"] = 
    glob["$buildClass"] = 
    glob["$Event"] = null;
    if( glob["XML"] ) glob["XML"] = null
  }

  if($globals.attachEvent) 
    $globals.attachEvent("onbeforeunload", clearSymbols);


})();

/*
 * platform-specific stuff
 *
 * Copyright (c) 2010 Evgen Burzak <buzzilo at gmail.moc>
 * Released under the MIT/X License
 */
$Unit(__PATH__, __FILE__, function(unit, root)
{
  $Package("platform", function(that) {

    var appVersion = !$isCLI && navigator.appVersion,
        userAgent = !$isCLI && navigator.userAgent,
        platform = !$isCLI && navigator.platform,
        vendor = !$isCLI && navigator.vendor;

    // @kudos to quirksmode.org for the code
    // http://www.quirksmode.org/js/detect.html
    //
    var versionSearchString;

    function searchString(data) {
      for (var i=0;i<data.length;i++)  {
        var dataString = data[i].s;
        var dataProp = data[i].p;
        versionSearchString = data[i].v || data[i].i;
        if (dataString) {
          if (dataString.indexOf(data[i].u) != -1)
            return data[i].i;
        }
        else if (dataProp)
          return data[i].i;
      }
    };

    function searchVersion(dataString) {
      var index = dataString.indexOf(versionSearchString);
      if (index == -1) return;
      return parseFloat(dataString.substring(index+versionSearchString.length+1));
    };
    
    var dataBrowser = [
      {
        // string
        s: userAgent,
        // subString
        u: "Chrome",
        // identity
        i: "Chrome"
      },
      {   
        s: userAgent,
        u: "OmniWeb",
        v: "OmniWeb/",
        i: "OmniWeb"
      },
      {
        s: vendor,
        u: "Apple",
        i: "Safari",
        v: "Version"
      },
      {
        p: $globals.opera,
        i: "Opera"
      },
      {
        s: vendor,
        u: "iCab",
        i: "iCab"
      },
      {
        s: vendor,
        u: "KDE",
        i: "Konqueror"
      },
      {
        s: userAgent,
        u: "Firefox",
        i: "Firefox"
      },
      {
        s: vendor,
        u: "Camino",
        i: "Camino"
      },
      {    // for newer Netscapes (6+)
        s: userAgent,
        u: "Netscape",
        i: "Netscape"
      },
      {
        s: userAgent,
        u: "MSIE",
        i: "Explorer",
        v: "MSIE"
      },
      {
        s: userAgent,
        u: "Gecko",
        i: "Mozilla",
        v: "rv"
      },
      {     // for older Netscapes (4-)
        s: userAgent,
        u: "Mozilla",
        i: "Netscape",
        v: "Mozilla"
      }
    ];

    var dataOS = [
      {
        s: platform,
        u: "Win",
        i: "Windows"
      },
      {
        s: platform,
        u: "Mac",
        i: "Mac"
      },
      {
        s: userAgent,
        u: "iPhone",
        i: "iPhone/iPod"
      },
      {
        s: platform,
        u: "Linux",
        i: "Linux"
      }
    ];

    that.browser = $isCLI ? null : searchString(dataBrowser) || "An unknown browser";
    that.version = $isCLI ? null : searchVersion(userAgent)
        || searchVersion(appVersion)
        || "an unknown version";
    that.OS = $isCLI ? null : searchString(dataOS) || "an unknown OS";

    // check for proprietary DOM members to be sure user agent are not masked
    that.isIE = !!(root.uniqueID && root.expando && that.browser === "Explorer");
    that.ie = that.isIE ? that.version : 0;

    that.isFirefox = that.browser === "Firefox"; 
    that.firefox = that.isFirefox ? that.version : 0;

    that.isOpera = that.browser === "Opera";
    that.opera = that.isOpera ? that.version : 0;

    that.isWebKit = that.browser === "Chrome" || that.browser === "Safari"
    // todo webkit version
    that.webkit = that.isWebKit ? 1 : 0;

    that.isCLI = $isCLI
  });
});
/*
 * W3C package
 *
 * Copyright (c) 2010 Evgen Burzak <buzzilo at gmail.moc>
 * Released under the MIT/X License
 */
$Unit(__PATH__, __FILE__, function(unit){
  unit.Package("w3c", function(w3c){
    w3c.DOMException = _DOMException
  });
});

/*
 * Basic geometry lib
 *
 * Copyright (c) 2010 Evgen Burzak <buzzilo at gmail.moc>
 * Released under the MIT/X License
 */
$Unit(__PATH__, __FILE__, function(unit)
{
  unit.Package("geom", function(geom) {

    var _event = unit.Event();

    function dimToString(dim) {
      return ["(", dim.join(", "), ")"].join("");
    };

    /*
     * class Point
     */
    function Point (x, y) {
      if( Point.caller === Point ) return this;
      var point = new Point;
      if(arguments.length == 2)
        point.set(x, y);
      return point
    };

    Point.className = 'Point';

    Point.role = unit.Role( Point, {
      x: unit.Number,
      y: unit.Number
    })

    Point.prototype = {

      // get delta (vector) of two points
      "vectorTo" : function (x, y) 
      {
        if(arguments.length == 1) y = x.y, x = x.x;
        return new Point(
          (x > this.x ? 1 : -1) * (Math.max (this.x, x) - Math.min (this.x, x)),
          (y > this.y ? 1 : -1) * (Math.max (this.y, y) - Math.min (this.y, y)) 
        );
      },

      "set" : function (x, y) {
          this.x = x
          this.y = y
          return this
      },

      "toString" : function() {
        return(dimToString ([this.x, this.y]));
      },

      "clone" : function() {
        return Point(this.x, this.y)
      }

    };
    
    /*
     * class Rectangle
     */
    function Rectangle (x, y, w, h) {
      if( Rectangle.caller === Rectangle ) return this;
      var rect = new Rectangle;
      if(arguments.length == 4)
        rect.set(x, y, w, h)
      return rect
    };

    Rectangle.className = 'Rectangle';

    Rectangle.role = unit.Role( Rectangle, {
      width: unit.Number,
      height: unit.Number
    }, Point.role)

    Rectangle.prototype = {

      "set" : function(x, y, w, h) {
        this.x = x
        this.y = y
        this.width = w
        this.height = h
        return this
      },
      "isPointWithin" : function(x, y) {
        if (arguments.length == 1) {
            y = x.y
            x = x.x
        }
        return (x>this.x && y>this.y && 
                x<this.x+this.width && y<this.y+this.height);
        
      },
      "clone" : function() {
          return Rectangle(this.x, this.y, this.width, this.height)
      },
      "toString" : function() {
        return(dimToString ([this.x, this.y, this.width, this.height]));
      }
    };

    /*
     * class Matrix2d
     *
     * Premultiplying transformation matrix in two-dimensional space.
     * 
     * | a c dx |
     * | b d dy |
     * | 0 0 1  |
     *
     * or matrix = [a, b, c, d, dx, dy]
     * 
     */
    function Matrix2d(a, b, c, d, dx, dy) { 

      if( Matrix2d.caller === Matrix2d ) return this;
      var self = new Matrix2d;

      self.matrix = unit.VectorArray(6, unit.Float(32))

      if (!arguments.length) {
        return self;
      }
      else if ( unit.Type.is_a( a, Matrix2d ) ) {
        b = self.matrix, c = a.matrix
        b[0] = c[0]
        b[1] = c[1]
        b[2] = c[2]
        b[3] = c[3]
        b[4] = c[4]
        b[5] = c[5]
      } else if (arguments.length === 6) {
        self.matrix[0] = a
        self.matrix[1] = b
        self.matrix[2] = c
        self.matrix[3] = d
        self.matrix[4] = dx
        self.matrix[5] = dy
      } else 
        throw new Error("Matrix2d: syntax error");

      return self
    };

    Matrix2d.prototype = {

      "identity" : function () {
        this.matrix[0] = 1;
        this.matrix[1] = 0;
        this.matrix[2] = 0;
        this.matrix[3] = 1;
        this.matrix[4] = 0;
        this.matrix[5] = 0;
        return this;
      },

      /**
        Translates a transformation matrix by x and y.
        */
      "translate" : function(x, y) {
        var m = this.matrix
        m[4] = m[0]*x + m[2]*y;
        m[5] = m[1]*x + m[3]*y;
        return this;
      },

      /**
        Scales a transformation matrix by sx and sy.
        */
      "scale" : function(sx, sy) {
        /*
        var scale = Matrix2d(sx, 0, 0, sy, 0, 0)
        this.multiplyMatrix(scale)
        */
        var m = this.matrix

        m[0] *= sx;
        m[2] *= sx;
        m[1] *= sy;
        m[3] *= sy;

        return this

      },

      /**
        Rotates a transformation matrix by angle.
        */
      "rotate" : function(angle) {
        /*
        var cos = Math.cos(angle),
            sin = Math.sin(angle);

        var rot = Matrix2d(
          cos, sin,
          -sin, cos,
          0, 0 
        );

        return this.multiplyMatrix(rot);
        */
        var m1 = this.matrix
        var c = Math.cos(angle)
        var s = Math.sin(angle)

        var m11 = m1[0]*c + m1[1]*s
        var m12 = m1[2]*c + m1[3]*s
        var m21 = m1[0]*-s + m1[1]*c
        var m22 = m1[2]*-s + m1[3]*c

        m1[0] = m11
        m1[1] = m12
        m1[2] = m21
        m1[3] = m22

        return this

      },

      /**
        Multiplies the vector [x, y, 1] with the 3x2 matrix.
        */
      "multiplyPoint" : function(p) {
        var m = this.matrix;
        var x = p.x, y = p.y;
        return new Point(
          x*m[0] + y*m[2] + m[4],
          x*m[1] + y*m[3] + m[5]
        );
      },

      /**
        Multiplies two 3x2 affine 2D column-major transformation matrices with
        each other and stores the result in the first matrix.

        Returns the multiplied matrix Matrix2d.
        */
      "multiplyMatrix" : function(m2) {

        var m1 = this.matrix
        m2 = m2.matrix

        var a = m1[0]*m2[0] + m1[2]*m2[1]
        var b = m1[1]*m2[0] + m1[3]*m2[1]

        var c = m1[0]*m2[2] + m1[2]*m2[3]
        var d = m1[1]*m2[2] + m1[3]*m2[3]

        var dx = m1[0]*m2[4] + m1[2]*m2[5] + m1[4]
        var dy = m1[1]*m2[4] + m1[3]*m2[5] + m1[5]

        m1[0] = a
        m1[1] = b
        m1[2] = c
        m1[3] = d
        m1[4] = dx
        m1[5] = dy

        return this
      },

      /**
        Inverts a 3x2 affine 2D column-major matrix.
        */
      "invert" : function() {

        var m = this.matrix
        var d = 1 / (m[0]*m[3]-m[1]*m[2])
        this.matrix.set([
          m[3]*d, -m[1]*d,
          -m[2]*d, m[0]*d,
          d*(m[2]*m[5]-m[3]*m[4]), d*(m[1]*m[4]-m[0]*m[5])
        ]) 

        return this;
      },

      "clone" : function () {
        return Matrix2d(this);
      },

      "toString" : function () {
        var m = this.matrix
        return dimToString([m[0], m[1], m[2], m[3], m[4], m[5]]);
      }

    }

    Matrix2d.className = 'Matrix2d';

    geom.Point = Point;
    geom.Rectangle = Rectangle;
    geom.Matrix2d = Matrix2d;

    _event.once('initialize', function(){
      unit.Class.registerClasses(Point, Rectangle, Matrix2d)
    });

  });
});

// is it CLI or Worker instance ?
// just fire initialize at the end of script, because of some envs does not provide
// setTimeout/Interval method
if($isCLI || $isWorker) {
    __init__.done = true
    // fixme is the content really loaded?
    _Event.dispatch("contentloaded");
}
})();
// End body

$jooscript = '(dev)';

